package com.um.jdy.app.charge.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.common.models.AlipayTradeCreateResponse;
import com.baomidou.lock.annotation.Lock4j;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingReceiver;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingRequest;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.um.jdy.app.charge.entity.dto.EBStartParam;
import com.um.jdy.app.charge.entity.vo.EBOrderConfirmVO;
import com.um.jdy.app.charge.scheduled.EBOrderTask;
import com.um.jdy.app.core.manager.OrderRedisTemplate;
import com.um.jdy.app.device.manager.DeviceManager;
import com.um.jdy.baofu.api.BaoFuAccountService;
import com.um.jdy.baofu.api.BaofuPayService;
import com.um.jdy.baofu.entity.account.ContentBodyEntity;
import com.um.jdy.baofu.entity.account.RsultBodyEntity;
import com.um.jdy.baofu.entity.account.ValuesAcctInfoEntity;
import com.um.jdy.baofu.entity.account.ValuesActionEntity;
import com.um.jdy.baofu.utils.FormatUtil;
import com.um.jdy.common.activity.code.CouponsCode;
import com.um.jdy.common.activity.entity.vo.CouponsUserDetailVO;
import com.um.jdy.common.activity.entity.vo.DiscountsVO;
import com.um.jdy.common.activity.entity.vo.StationAvailableCouponsVO;
import com.um.jdy.common.activity.enums.ActivityEnum;
import com.um.jdy.common.activity.service.CouponsUserService;
import com.um.jdy.common.activity.service.DiscountsStationService;
import com.um.jdy.common.baofu.entity.po.BaofuAccountDetails;
import com.um.jdy.common.baofu.entity.po.BaofuRefund;
import com.um.jdy.common.baofu.service.BaofuAccountDetailsService;
import com.um.jdy.common.baofu.service.BaofuRefundService;
import com.um.jdy.common.base.enums.YesOrNo;
import com.um.jdy.common.charge.code.OrderCode;
import com.um.jdy.common.charge.entity.po.*;
import com.um.jdy.common.charge.entity.vo.OrderVO;
import com.um.jdy.common.charge.enums.OrderAction;
import com.um.jdy.common.charge.enums.OrderEnum;
import com.um.jdy.common.charge.enums.OrderException;
import com.um.jdy.common.charge.enums.OrderStopReason;
import com.um.jdy.common.charge.service.*;
import com.um.jdy.common.commons.manager.WxManager;
import com.um.jdy.common.commons.properties.HshChargingProperties;
import com.um.jdy.common.commons.service.CommissionService;
import com.um.jdy.common.device.code.DeviceCode;
import com.um.jdy.common.device.entity.po.*;
import com.um.jdy.common.device.enums.DeviceEnum;
import com.um.jdy.common.device.service.*;
import com.um.jdy.common.finance.entity.po.*;
import com.um.jdy.common.finance.enums.FinancialEnum;
import com.um.jdy.common.finance.service.*;
import com.um.jdy.common.member.code.UserCode;
import com.um.jdy.common.member.entity.po.MemberUser;
import com.um.jdy.common.member.entity.po.Wallet;
import com.um.jdy.common.member.enums.PayEnum;
import com.um.jdy.common.member.service.MemberUserService;
import com.um.jdy.common.member.service.WalletService;
import com.um.jdy.common.month.entity.po.CardUser;
import com.um.jdy.common.month.service.CardUserService;
import com.um.jdy.common.platform.entity.po.App;
import com.um.jdy.common.platform.entity.po.SharingSetting;
import com.um.jdy.common.platform.service.AppService;
import com.um.jdy.common.platform.service.MerchantService;
import com.um.jdy.common.platform.service.SharingSettingService;
import com.um.jdy.common.push.service.PushService;
import com.um.jdy.common.sharing.entity.po.Receiver;
import com.um.jdy.common.sharing.entity.po.Records;
import com.um.jdy.common.sharing.service.ReceiverService;
import com.um.jdy.common.sharing.service.RecordsService;
import com.um.jdy.rpc.api.RpcEBDeviceService;
import com.um.jdy.rpc.entity.EBPort;
import com.um.jdy.rpc.enums.DeviceProtocolEnum;
import com.um.jdy.rpc.factory.ServiceFactory;
import com.um.jdy.rpc.notify.RpcEBOrderNotifyService;
import com.um.springboot.starter.code.CommonCode;
import com.um.springboot.starter.exception.ServiceException;
import com.um.springboot.starter.orm.manager.BaseManager;
import com.um.springboot.starter.properties.HshProperties;
import com.um.springboot.starter.utils.*;
import com.um.springcloud.dubbo.cluster.DeviceKey;
import com.um.weixin.pay.service.WxBasePayService;
import com.um.weixin.pay.service.WxSharingService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Title
 * @Description
 * @Author renjunwei
 * @Date 2023/5/22 10:37
 */
@Slf4j
@Service
@DubboService
public class EBOrderManager extends BaseManager<EbOrderService> implements RpcEBOrderNotifyService {

    @Autowired
    PileService pileService;

    @Autowired
    GunService gunService;

    @Autowired
    MemberUserService userService;

    @Autowired
    OrderService orderService;

    @Autowired
    StationService stationService;

    @Autowired
    FeeEbPriceService feeEbPriceService;

    @Autowired
    FeeEbPowerService feeEbPowerService;

    @Autowired
    WalletService walletService;

    @Autowired
    MerchantService merchantService;

    @Autowired
    DeviceManager deviceManager;

    @Autowired
    HshProperties hshProperties;

    @Autowired
    EBOrderManager self;

    @Autowired
    HttpServletRequest request;

    @Autowired
    TaskScheduler taskScheduler;

    @Autowired
    EbOrderService ebOrderService;

    @Autowired
    EBOrderTask ebOrderTask;

    @Autowired
    UserBillService userBillService;

    @Autowired
    PlatformBillService platformBillService;

    @Autowired
    DataLogService dataLogService;

    @Autowired
    OrderPowerService orderPowerService;

    @Autowired
    MerchantBillService merchantBillService;

    @Autowired
    PlatformProfitBillService platformProfitBillService;


    @Autowired
    OrderCommissionService orderCommissionService;

    @Autowired
    PortAlarmRecordService alarmRecordService;

    @Autowired
    WxSharingService wxSharingService;

    @Autowired
    WxBasePayService wxPayService;

    @Autowired
    ReceiverService receiverService;

    @Autowired
    SharingSettingService sharingSettingService;

    @Autowired
    RecordsService recordsService;

    @Autowired
    OrderSkipPowerService orderSkipPowerService;

    @Autowired
    CommissionService commissionService;

    @Autowired
    OrderSharingService orderSharingService;

    @Autowired
    OrderEbPowerService orderEbPowerService;



    @Autowired
    OrderSkipService orderSkipService;

    @Autowired
    OrderEnergyService orderEnergyService;

    @Autowired
    OrderEbTimeService orderEbTimeService;

    @Autowired
    HshChargingProperties hshChargingProperties;

    @Autowired
    WxManager wxManager;

    @Autowired
    OrderRedisTemplate orderRedisTemplate;

    @Autowired
    ServiceFactory serviceFactory;

    @Autowired
    FeeService feeService;

    @Autowired
    PushService pushService;

    @Autowired
    CardUserService cardUserService;

    @Autowired
    CouponsUserService couponsUserService;

    @Autowired
    DiscountsStationService discountsStationService;
    @Autowired
    BaofuPayService baofuPayService;

    @Autowired
    AppService appService;
    @Autowired
    BaofuRefundService baofuRefundService;

    @Autowired
    private BaofuAccountDetailsService baofuAccountDetailsService;

    @Autowired
    BaoFuAccountService baoFuAccountService;



    /**
     * 开启充电
     * @param param
     * @return
     */
    @Transactional
    public Map startCharge(EBStartParam param) {
        Pile pile = pileService.getEntity("code", param.getCode());
        if (pile == null) {
            throw new ServiceException(DeviceCode.NoDevice);
        }

        if (!DeviceEnum.OpenStatus.Enable.name().equals(pile.getOpenState())) {
            throw new ServiceException(DeviceCode.DeviceNotEnabled);
        }

        if (!DeviceEnum.DeviceStatus.Online.name().equals(pile.getDeviceStatus())) {
            throw new ServiceException(DeviceCode.DeviceOffline);
        }

        Station station = stationService.getEntity(pile.getDeviceStationId());
        if (station == null) {
            throw new ServiceException(DeviceCode.NoStation);
        }

        Gun gun = gunService.getEntity(new String[]{"device_pile_id", "port"}, new Object[]{pile.getDevicePileId(), param.getGunNum()});
        if (gun == null) {
            throw new ServiceException(DeviceCode.NoGun);
        }

        if (!DeviceEnum.PortStatus.Available.name().equals(gun.getStatus())) {
            throw new ServiceException(DeviceCode.Unavailable);
        }

        //设置充电单价
        FeeEbPrice feePrice = feeEbPriceService.getEntity(new String[]{"device_fee_id", "device_fee_eb_price_id"},
                new String[]{pile.getDeviceFeeId(), param.getDeviceFeePriceId()});
        if (feePrice == null) {
            throw new ServiceException(DeviceCode.NoFee);
        }

        //价格(分)
        int payAmount = feePrice.getPrice();

        MemberUser user = userService.get();
        String uid = user.getMemberUserId();

        //判断用户是否有月卡
        boolean hasMonthCard = deviceManager.hasMonthCard(uid, pile.getDeviceStationId());
        //是否月卡支付
        boolean isMonthPay = PayEnum.PayWay.MonthCard == param.getPayWay();
        //判断用户是否充电白名单 true-是 false-否
        boolean freeStatus = deviceManager.checkFreeUser(uid, pile.getDeviceStationId(), pile.getDevicePileId(),pile.getComId())
                || (isMonthPay && hasMonthCard);

        // 检查充电口是否已被其他订单占用
        if (StrUtil.isNotBlank(gun.getOrderNo())) {
            Order otherOrder = orderService.getEntity("order_no", gun.getOrderNo());
            // 占用充电口的订单用户是当前用户，则取消旧订单
            if (otherOrder != null && uid.equals(otherOrder.getMemberUserId()) &&
                    PayEnum.Status.UnPayed.name().equals(otherOrder.getPayStatus())) {
                try {
                    self.cancelCharge(gun.getOrderNo());

                }catch (Exception ex){
                    ex.printStackTrace();
                    log.error(ex.getMessage());
                }
            } else {
                throw new ServiceException(DeviceCode.PortOccupyByOrder);
            }
        }

        Fee fee = feeService.getEntity(pile.getDeviceFeeId());
        if(fee == null){
            throw new ServiceException(DeviceCode.NoFee);
        }

        //非白名单用户检查余额是否足够
        if (!freeStatus) {
            if (PayEnum.PayWay.Wallet == param.getPayWay() && payAmount > walletService.getBalance(uid,pile.getComId())) {
                throw new ServiceException(UserCode.NoBalance);
            }
        }

        //月卡支付，如果有月卡订单，则不能再启动
        if (isMonthPay && hasMonthCard) {
            if(orderService.getList(new String[]{"member_user_id","status","pay_way"},
                    new Object[]{uid,OrderEnum.Status.Charging.name(),PayEnum.PayWay.MonthCard.name()}).size() > 0) {
                throw new ServiceException(OrderCode.MonthCardOnlyOrder);
            }
        }

        String orderNo = OrderUtil.getOrderNo();
        String outTradeNo = OrderUtil.getWxOrderNo();

        Order order = new Order();
        order.setOrderNo(orderNo);
        order.setOutTradeNo(outTradeNo);
        order.setDeviceStationId(pile.getDeviceStationId());
        order.setDevicePileId(pile.getDevicePileId());
        order.setDeviceName(pile.getName());
        order.setDeviceImei(pile.getImei());
        order.setDeviceCode(param.getCode());
        order.setDeviceGunId(gun.getDeviceGunId());
        order.setPort(gun.getPort());
        order.setMemberUserId(uid);
        order.setComId(pile.getComId());
        order.setPlatformMerchantId(station.getPlatformMerchantId());
        order.setCreateTime(DateUtil.date());
        order.setPayAmount(freeStatus ? 0 : payAmount);//免费付款为0
        order.setPayStatus(PayEnum.Status.UnPayed.name());
        order.setPayWay(param.getPayWay().name());
        order.setStatus(OrderEnum.Status.NotStarted.name());
        order.setItemPrice(getItemPriceText(feePrice));//TODO 1元3小时
        order.setIsFree(freeStatus ? YesOrNo.Yes.name() : YesOrNo.No.name());//免费订单
        order.setIsMonth(isMonthPay ? YesOrNo.Yes.name() : YesOrNo.No.name());//是否月卡订单
        order.setDeviceType(pile.getDeviceType());
        order.setDeviceFeeId(pile.getDeviceFeeId());
        order.setAutoUseCoupons(YesOrNo.Yes.name());
        if(isMonthPay || freeStatus || null == param.getAutoUseCoupons() || !param.getAutoUseCoupons()){
            order.setAutoUseCoupons(YesOrNo.No.name());
            if(!isMonthPay && !freeStatus && StrUtil.isNotBlank(param.getActivityCouponsId())){
                CouponsUserDetailVO userCoupons = couponsUserService.getUserCoupons(param.getActivityCouponsId(), uid);
                if(null == userCoupons){
                    throw new ServiceException(CouponsCode.CouponsNotExist);
                }
                order.setActivityCouponsUserId(userCoupons.getActivityCouponsUserId());
                couponsUserService.saveCouponsUse(userCoupons.getActivityCouponsUserId());
            }
        }

        orderService.save(order);

        EbOrder ebOrder = new EbOrder();
        ebOrder.setChargePower(0);
        ebOrder.setFeeType(fee.getFeeType());
//        ebOrder.setEnergyPrice(fee.getEnergyPrice());
//        ebOrder.setServicePrice(feePrice.getPrice());
        ebOrder.setChargeOrderId(order.getChargeOrderId());


        //用户如果还没有填写省市区，则自动保存
        if(StringUtil.isEmpty(user.getProvince())){
            userService.saveLocation(user,station.getProvince(),station.getCity(),station.getArea());
        }

        if(StringUtil.equals(ebOrder.getFeeType(),OrderEnum.FeeType.Time.name())){
            FeeEbPower feePower = feeEbPowerService.getViewModel("get_eb_power_price_list", FeeEbPower.class, new String[]{pile.getDeviceFeeId()});
            if(feePower == null){
                throw new ServiceException(DeviceCode.NoFee);
            }

            //功率(W)
            int power = feePower.getEndPower();
            //最低档功率的单价（分）
            int powerPrice = feePower.getPrice();
            //秒
            int timeLength = payAmount * 3600 / powerPrice;

            order.setPaySeconds(timeLength);
            ebOrder.setStartPower(feePower.getStartPower());
            ebOrder.setEndPower(feePower.getEndPower());
            ebOrder.setEnergyPrice(fee.getEnergyPrice());//TODO PRICE
            ebOrder.setServicePrice(feePower.getPrice());
        }else{
            String currentTime = DateUtil.format(new Date(),"HH:mm");
            FeeEbTime feeEbTime = service.getViewModel("get_energy_price_by_time",FeeEbTime.class,new Object[]{fee.getComId(),fee.getDeviceFeeId(),currentTime,currentTime});
            if(feeEbTime == null){
                throw new ServiceException("价格不存在！");
            }

            //当前时段电费单价（分）
            int timePrice = feeEbTime.getPrice()+feeEbTime.getServiceFee();

            order.setPaySeconds(12 * 3600);
            ebOrder.setStartPower(0);
            ebOrder.setEndPower(hshChargingProperties.getMaxPower());
            ebOrder.setEnergyPrice(fee.getEnergyPrice());//TODO PRICE
        }

        orderService.save(order);
        ebOrderService.save(ebOrder);
        //记录分佣副本
        orderSharingService.addOrderSharing(order);
        //记录订单功率档位副本
        orderEbPowerService.addOrderPower(pile.getDeviceFeeId(),order.getChargeOrderId());
        //记录订单时段计费副本
        orderEbTimeService.addOrderTime(pile.getDeviceFeeId(),order.getChargeOrderId());

        // 白名单不需要支付
        if (!freeStatus) {
            order.setPayWay(param.getPayWay().name());


            if (PayEnum.PayWay.Wxpay == param.getPayWay()) { //微信支付
                // 充电口占位
                Gun updateGun = new Gun();
                updateGun.setDeviceGunId(gun.getDeviceGunId());
                updateGun.setOrderNo(orderNo);
                gunService.save(updateGun);

                // 判断是否需要分账
                if(isProfitSharing(getComId())){
                    order.setIsProfitSharing(YesOrNo.Yes.name());
                    orderService.save(order);
                }

                //预下单，生成支付参数
                String openId = user.getMiniOpenId();
                /**
                 * todo 修改为宝付支付
                String notifyUrl = StrUtil.builder(hshProperties.getConfig().getDomain(),
                        "/api/v1/order/charge/eb/wxpay/notify/", userService.getComId()).toString();
                Date timeExpire = DateUtil.date().offset(DateField.MINUTE, 30);

                WxPayUnifiedOrderV3Result.JsapiResult jsapiResult = null;
                try {
                    wxManager.getPayService(userService.getComId());
                    jsapiResult = wxPayService.createOrderByJsapi(outTradeNo, openId,
                            PayUtil.toTotalFee(payAmount), PayEnum.Title.Charge.getValue(), notifyUrl, isProfitSharing(getComId()), timeExpire);
                } catch (WxPayException e) {
                    throw new RuntimeException(e);
                 Map<String, Object> returnData = BeanUtil.beanToMap(jsapiResult, true, true);
                 returnData.put("charge_order_id", order.getChargeOrderId());
                 returnData.put("order_no", orderNo);
                }*/
                String type = "chargeEb";
                App app = appService.getEntity("com_id", userService.getComId());
                Map<String, Object> returnData = baofuPayService.createOrderByJsapi(outTradeNo,PayUtil.toTotalFee(payAmount),PayEnum.Title.Charge.getValue(),openId,app.getMiniAppId(),app.getWxMchId(),type,userService.getComId());
                //Map<String, Object> returnData = null;
                returnData.put("charge_order_id", order.getChargeOrderId());
                returnData.put("order_no", orderNo);

                // 创建1分钟后未支付自动取消任务
                taskScheduler.schedule(() -> ebOrderTask.timeoutUnpaidTask(orderNo),
                        DateUtil.date().offset(DateField.SECOND, 60));

                return returnData;
            } else if (PayEnum.PayWay.Alipay == param.getPayWay()) { //支付宝支付
                // 充电口占位
                Gun updateGun = new Gun();
                updateGun.setDeviceGunId(gun.getDeviceGunId());
                updateGun.setOrderNo(orderNo);
                gunService.save(updateGun);

                //支付宝支付
                String notifyUrl = StrUtil.builder(hshProperties.getConfig().getDomain(), "/api/v1/order/charge/alipay/notify").toString();
                AlipayTradeCreateResponse alipayTradeCreateResponse = null;
                try {
                    alipayTradeCreateResponse = Factory.Payment.Common()
                            .asyncNotify(notifyUrl)
                            .optional("timeout_express", "10m") //订单超时时间
                            .create(PayEnum.Title.Charge.getValue(), outTradeNo, PayUtil.toDoubleAmountStr(payAmount), user.getAlipayUserId());
                } catch (Exception e) {
                    log.error("支付宝创建订单失败", e);
                    throw new ServiceException("支付宝创建订单失败");
                }

                log.info("支付宝下单：" + cn.hutool.json.JSONUtil.toJsonStr(alipayTradeCreateResponse));

                if (!ResponseChecker.success(alipayTradeCreateResponse)) {
                    throw new ServiceException(CommonCode.Failed.getCode(), alipayTradeCreateResponse.getSubMsg());
                }

                Map payInfo = alipayTradeCreateResponse.toMap();
                payInfo.put("order_no", orderNo);
                payInfo.put("charge_order_id", order.getChargeOrderId());


                // 创建1分钟后未支付自动取消任务
                taskScheduler.schedule(() -> ebOrderTask.timeoutUnpaidTask(orderNo),
                        DateUtil.date().offset(DateField.SECOND, 60));

                return payInfo;

            } else { //余额支付
                Date payTime = DateUtil.date();

                //记录钱包流水，金额为付款金额
                Wallet memberWallet = new Wallet();
                memberWallet.setMemberUserId(uid);
                memberWallet.setOrderNo(orderNo);
                memberWallet.setNo(OrderUtil.getOrderNo());
                memberWallet.setType(FinancialEnum.IncomeOrExpend.Expend.name());
                memberWallet.setAmount(payAmount);
                memberWallet.setStatus(FinancialEnum.BillStatus.Effective.name());
                memberWallet.setEvent(FinancialEnum.WalletBillEvent.Charge.name());
                memberWallet.setCreateTime(payTime);
                walletService.save(memberWallet);

                self.orderPaid(orderNo, payTime);

                return MapUtil.builder().put("order_no", orderNo).put("charge_order_id", order.getChargeOrderId()).build();
            }
        } else {
            Date payTime = DateUtil.date();
            self.orderPaid(orderNo, payTime);
            return MapUtil.builder().put("order_no", orderNo).put("charge_order_id", order.getChargeOrderId()).build();
        }

    }

    /**
     * 订单支付后续处理
     *
     * @param orderNo
     * @param payTime
     * @throws Exception
     */
    @Lock4j(name = "processUnpaidOrder", keys = "#orderNo")
    @Transactional
    public void orderPaid(String orderNo, Date payTime) {
        // 重新查一遍订单，避免落锁前订单已被改动
        Order order = orderService.getRow("order_no", orderNo);
        if (order == null) {
            log.error("订单{}不存在！", orderNo);
            return;
        }

        if (PayEnum.Status.Payed.name().equals(order.getPayStatus())) {
            log.warn("订单{}已支付，忽略orderPaid", orderNo);
            return;
        }

        Order updateOrder = new Order();
        updateOrder.setChargeOrderId(order.getChargeOrderId());
        updateOrder.setPayTime(payTime);
        updateOrder.setPayStatus(PayEnum.Status.Payed.name()); //已支付
        orderService.updateRow(updateOrder);

        String pileId = order.getDevicePileId();
        Pile pile = pileService.getRow(pileId);
        if (pile == null) {
            log.error("设备" + pileId + "不存在！");
            return;
        }

        // 非白名单记录流水
        if (!isFreeOrder(order)) {
            // 微信或支付宝支付记录流水
            if (!PayEnum.PayWay.Wallet.name().equals(order.getPayWay())) {
                //插入用户账单流水：充电消费
                UserBill userBill = new UserBill();
                userBill.setComId(order.getComId());
                userBill.setMemberUserId(order.getMemberUserId());
                userBill.setNo(OrderUtil.getOrderNo());
                userBill.setOutTradeNo(order.getOutTradeNo());
                userBill.setOrderNo(orderNo);
                userBill.setAmount(order.getPayAmount());
                userBill.setType(FinancialEnum.IncomeOrExpend.Expend.name());//收入支出类型：0-收入，1-支出
                userBill.setEvent(FinancialEnum.UserBillEvent.Charge.name());
                userBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
                userBill.setCreateTime(DateUtil.date());
                userBillService.saveRow(userBill);

                //插入平台账单流水：充电消费
                PlatformBill platformBill = new PlatformBill();
                platformBill.setComId(order.getComId());
                platformBill.setNo(OrderUtil.getOrderNo());
                platformBill.setOutTradeNo(order.getOutTradeNo());
                platformBill.setOrderNo(orderNo);
                platformBill.setAmount(order.getPayAmount());
                platformBill.setType(FinancialEnum.IncomeOrExpend.Income.name());//收入支出类型：0-收入，1-支出
                platformBill.setEvent(FinancialEnum.PlatformBillEvent.Charge.name());
                platformBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
                platformBill.setCreateTime(DateUtil.date());
                platformBillService.saveRow(platformBill);
            }
        }


        //订单超时未支付已被自动取消，执行退款操作
        if (OrderEnum.Status.Completed.name().equals(order.getStatus())) {
            log.error("订单{}超时未支付已被自动取消，执行退款操作", orderNo);
            //int chargeSeconds = getOrderChargeSeconds(order, DateUtil.date());

            saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.OrderFinish,new Date(),
                    "{}","订单超时未支付已被自动取消");
            self.chargeFinish(orderNo,OrderEnum.Status.Cancel,OrderStopReason.EB.SYS_END.name(), true);


            return;
        }

        //更新设备充电口状态
        Gun gun = gunService.getRow(order.getDeviceGunId());
        if (gun == null) {
            log.error("充电口" + order.getDeviceGunId() + "不存在！");
            return;
        }
        gun.setStatus(DeviceEnum.PortStatus.Preparing.name()); //启动中
        gun.setOrderNo(orderNo);
        gunService.updateRow(gun);

        //添加到redis缓存
        orderRedisTemplate.setOrder(order.getDeviceCode(),order.getPort(),OrderEnum.Status.NotStarted,order.getChargeOrderId());

        String command = serviceFactory.getRpcEBDeviceService(pile.getProtocol()).reqStartCharge(order.getOrderNo(), new DeviceKey(pile.getImei()), gun.getPort(), order.getPaySeconds(),
                getOverPower(order.getComId(),order.getMemberUserId(),order.getDeviceStationId(),order.getPayWay()),
                order.getPayAmount());

        saveChargeData(order.getComId(),order.getChargeOrderId(), OrderAction.EB.StartChargeReq, DateUtil.date(), command,"无");

        // 创建15秒后未启动播放提示语音
//        taskScheduler.schedule(() -> ebOrderTask.timeoutPlayTTSTask(orderNo),
//                DateUtil.date().offset(DateField.SECOND, 15));

        // 创建30秒后未启动自动取消任务
        taskScheduler.schedule(() -> ebOrderTask.timeoutNotStartedTask(orderNo),
                DateUtil.date().offset(DateField.SECOND, 30));
    }

    /**
     * 确认订单
     * @param chargeOrderId
     * @return
     */
    public EBOrderConfirmVO confirm(String chargeOrderId){
        //更新订单状态
        Order order = orderService.getRow(chargeOrderId);
        if (order == null) {
            throw new ServiceException(OrderCode.NoOrder);
        }

        int payAmount = order.getOrderAmount();

        CouponsUserDetailVO selectedCoupons = null;
        DiscountsVO selectedDiscount = null;

        if(!isFreeOrder(order) && !YesOrNo.Yes.name().equals(order.getIsMonth())){
            // 自动使用优惠券
            if(YesOrNo.Yes.name().equals(order.getAutoUseCoupons())){
                List<StationAvailableCouponsVO> couponsList = couponsUserService.getStationAvailableList(order.getDeviceStationId(),
                        DeviceEnum.Type.EB.name(), order.getMemberUserId());
                StationAvailableCouponsVO stationAvailableCouponsVO = couponsList.stream().filter(item -> item.getLimitMoney() <= order.getOrderAmount()).findFirst().orElse(null);
                selectedCoupons = BeanUtil.toBean(stationAvailableCouponsVO, CouponsUserDetailVO.class);
                if(null != selectedCoupons){
                    payAmount -= selectedCoupons.getMoney();
                    couponsUserService.saveCouponsUse(selectedCoupons.getActivityCouponsUserId());
                }

                // 已选中优惠券
            }else if(StrUtil.isNotBlank(order.getActivityCouponsUserId())){
                selectedCoupons = couponsUserService.getUserCoupons(order.getActivityCouponsUserId());
                if(selectedCoupons.getLimitMoney() <= order.getOrderAmount()){
                    payAmount -= selectedCoupons.getMoney();
                }else{
                    selectedCoupons = null;
                }
            }

            if(null == selectedCoupons || YesOrNo.Yes.name().equals(selectedCoupons.getIsActivityMerge())){
                List<DiscountsVO> discountsList = discountsStationService.getDiscountsList(order.getDeviceStationId(),
                        DeviceEnum.Type.EB.name());
                selectedDiscount = discountsList.stream().filter(item ->
                        item.getFullPrice() <= order.getOrderAmount()).findFirst().orElse(null);
                if(null != selectedDiscount){
                    payAmount -= ActivityEnum.DiscountsType.Money.name().equals(selectedDiscount.getType()) ?
                            selectedDiscount.getPrice() : payAmount * selectedDiscount.getScale() / 100;
                }
            }
        }


        if(payAmount < 0){
            payAmount = 0;
        }

        EBOrderConfirmVO confirm = new EBOrderConfirmVO();
        confirm.setOrder(BeanUtil.toBean(order, OrderVO.class));
        confirm.setSelectedCoupons(selectedCoupons);
        confirm.setDiscounts(selectedDiscount);
        confirm.setPayAmount(payAmount);
        return confirm;

    }


    /**
     * 统一处理订单结束方式 注意：本方法已按新设备及金额单位为分来处理，不需要再修改，除非有BUG
     *
     * @param orderNo        订单号
     * @param reason        设备结束类型
     * @param forceRefund 是否强行退款，无论订单是否结束都执行退款流程
     */
    @Lock4j(keys = "#orderNo")
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void chargeFinish(String orderNo,OrderEnum.Status status, String reason, boolean forceRefund) {
        //更新订单状态
        Order order = orderService.getRow("order_no", orderNo);
        if (order == null) {
            return;
        }

//        if(StringUtil.equals(PayEnum.Status.UnPayed.name(),order.getPayStatus())){
//            return;
//        }

        EbOrder ebOrder = ebOrderService.getRow("charge_order_id", order.getChargeOrderId());
        Long beginEnergy = orderService.getBeginEnergy(order.getChargeOrderId());
        Long endEnergy = orderService.getEndEnergy(order.getChargeOrderId(),beginEnergy);
        int paySeconds = order.getPaySeconds();
        int chargeCapacity = orderService.getCapacity(order.getChargeOrderId());

        ebOrder.setBeginEnergy(beginEnergy);
        ebOrder.setEndEnergy(endEnergy);

        if (!forceRefund && OrderEnum.Status.Completed.name().equals(order.getStatus())) {
            if (chargeCapacity > ebOrder.getChargeCapacity()) {
                log.info("订单{}已结束，只更新已充电度数", orderNo);
                ebOrder.setChargeCapacity(chargeCapacity);

                order.setEndTime(DateUtil.date());
                order.setChargeCapacity(chargeCapacity);//多记录一个电量字段
                orderService.updateRow(order);
                ebOrderService.updateRow(ebOrder);
            } else {
                log.warn("订单{}已结束，忽略chargeFinish", orderNo);
            }
            return;
        }

        order.setStatus(status.name()); //充电完成
        if(StringUtil.isEmpty(order.getEndType())) {
            order.setEndType(reason);
        }

        //更新结束时间
        order.setEndTime(DateUtil.date());
        if (chargeCapacity > ebOrder.getChargeCapacity()) {
            ebOrder.setChargeCapacity(chargeCapacity);
            order.setChargeCapacity(chargeCapacity);//多记录一个电量字段
        }

        Gun gun = gunService.getRow(order.getDeviceGunId());
        if (gun != null) {
            // 订单号一致则将充电口状态改回空闲
            if (orderNo.equals(gun.getOrderNo())) {
                gun.setOrderNo("");
                gun.setStatus(DeviceEnum.PortStatus.Available.name());
                gunService.updateRow(gun);
            }
        } else {
            log.warn("订单{}充电充电口不存在，忽略更新充电口状态", orderNo);
        }

        String outTradeNo = order.getOutTradeNo();
        //避免充电停充没有上报秒数
        int chargeSeconds = getOnlineChargeSeconds(order);
        //取整分钟
        chargeSeconds = chargeSeconds / 60 * 60;
//        int chargeCecilSeconds = 0; //按30分钟取整充电时长
//        if (chargeSeconds >= 300) { //充电满5分钟才收费
//            chargeCecilSeconds = getCeilTime(chargeSeconds); //按30分钟取整
//            chargeCecilSeconds = Math.min(paySeconds, chargeCecilSeconds); //不能大于支付时长
//        }

        //log.info("eb order:{}-{}",chargeSeconds,chargeCecilSeconds);
        int chargeAmount = 0; //实际充电金额
        int returnAmount = 0; //退款金额
        //是否为宝付订单
        Boolean isBaofu = false;
        //非免费充电
        if (!isFreeOrder(order)) {

            int payAmount = order.getPayAmount();

            //按时间计费
            if(StringUtil.equals(ebOrder.getFeeType(),OrderEnum.FeeType.Time.name())) {

//                if (chargeCecilSeconds >= paySeconds) {
//                    chargeAmount = payAmount;
//                    returnAmount = 0;
//                } else {
//                    chargeAmount = (int) (ebOrder.getPowerPrice() * NumberUtil.div(chargeCecilSeconds, 3600));
//                    chargeAmount = Math.min(chargeAmount, payAmount);//不能大于支付金额
//                    returnAmount = payAmount - chargeAmount;
//                }


                int serviceFee = orderService.getTimeServiceFee(order,ebOrder.getServicePrice(),chargeSeconds);
                int energyFee =  orderService.getTimeEnergyFee(order,ebOrder.getEnergyPrice());
                ebOrder.setEnergyFee(energyFee);
                ebOrder.setServiceFee(serviceFee);

                order.setServiceFee(serviceFee);
                order.setEnergyFee(energyFee);

                chargeAmount = Math.min(energyFee + serviceFee, payAmount);//不能大于支付金额
                returnAmount = payAmount - chargeAmount;
            }else{
                adjustOrderEnergy(order, endEnergy);
                int energyFee = orderService.getEnergyFee(order.getChargeOrderId());
                int serviceFee = orderService.getServiceFee(order.getChargeOrderId());

                chargeAmount = Math.min(payAmount, energyFee + serviceFee);
                returnAmount = payAmount - chargeAmount;

                ebOrder.setEnergyFee(energyFee);
                ebOrder.setServiceFee(serviceFee);

                order.setEnergyFee(ebOrder.getEnergyFee());
                order.setServiceFee(ebOrder.getServiceFee());
            }

            if(YesOrNo.Yes.name().equals(order.getIsCoin())){
                returnAmount = 0;//投币不退款，返回金额设置为0
                chargeAmount = payAmount;
            }

            log.info("eb order amount:{}-{}",chargeAmount,returnAmount);

            order.setChargeAmount(chargeAmount);
            order.setOrderAmount(chargeAmount);
            order.setDuration(chargeSeconds);
            orderService.updateRow(order);

            ebOrder.setChargeSeconds(chargeSeconds);
            ebOrder.setEndEnergy(endEnergy);

            EBOrderConfirmVO confirm = confirm(order.getChargeOrderId());
            if(null != confirm.getSelectedCoupons()){
                order.setActivityCouponsUserId(confirm.getSelectedCoupons().getActivityCouponsUserId());
                order.setCouponsAmount(confirm.getSelectedCoupons().getMoney());
                order.setCouponsRemark(confirm.getSelectedCoupons().getTitle());
                returnAmount += confirm.getSelectedCoupons().getMoney();
            }else if(StrUtil.isNotBlank(order.getActivityCouponsUserId())){
                couponsUserService.returnCouponsUse(order.getActivityCouponsUserId());
            }
            if(null != confirm.getDiscounts()){
                order.setDiscountsAmount(confirm.getDiscounts().getPrice());
                order.setDiscountsType(confirm.getDiscounts().getType());
                order.setDiscountsRemark(confirm.getDiscounts().getTitle());
                returnAmount += confirm.getDiscounts().getPrice();
            }

            returnAmount = Math.min(returnAmount,order.getPayAmount());//添加判断：退款金额不能大于支付金额

            if (returnAmount > 0) {
                order.setReturnWay(order.getPayWay());
                order.setReturnTime(DateUtil.date());
                order.setReturnAmount(returnAmount);

                //原路退回
                if (!PayEnum.PayWay.Wallet.name().equals(order.getPayWay())) {//非余额支付
                    int totalFee = PayUtil.toTotalFee(payAmount);//支付的订单金额
                    int returnFee = PayUtil.toTotalFee(returnAmount);//退回金额

                    if (PayEnum.PayWay.Wxpay.name().equals(order.getPayWay())) {//退回微信零钱或银行卡
                        /** todo 修改为宝付退款
                        try {
                            wxManager.getPayService(order.getComId());
                            wxPayService.refundOrder(outTradeNo, OrderUtil.getWxOrderNo(), totalFee, returnFee);
                            order.setReturnStatus(OrderEnum.ReturnStatus.Success.name());//退款成功

                        } catch (WxPayException e) {
                            order.setReturnStatus(OrderEnum.ReturnStatus.Failure.name());//退款失败
                            log.error(StrUtil.format("订单{}微信退款异常", orderNo), e);

                            order.setExceptionType(OrderException.EB.RefundFailed.name());
                            order.setIsException(YesOrNo.Yes.name());
                            order.setExceptionStatus(YesOrNo.No.name());
                        }
                        */
                        try{
                            isBaofu = true;
                            String type ="chargeEbRefunZd";
                            String refundNo = OrderUtil.getWxOrderNo();
                            baofuPayService.refundOrder(outTradeNo, refundNo,totalFee,returnFee,type,order.getComId());
                            //回调里在进行操作
                            //order.setReturnStatus(OrderEnum.ReturnStatus.Success.name());//退款成功
                            order.setReturnStatus(OrderEnum.ReturnStatus.Refund.name());//退款中
                            BaofuRefund baofuRefund = new BaofuRefund();
                            baofuRefund.setComId(order.getComId());
                            baofuRefund.setRefundAmount(returnFee);
                            baofuRefund.setOutRefundNo(refundNo);
                            baofuRefund.setRefundState("REFUND");
                            baofuRefund.setOutTradeNo(outTradeNo);
                            baofuRefund.setType(type);
                            baofuRefundService.addRefund(baofuRefund);
                        }catch (ServiceException e){
                            order.setReturnStatus(OrderEnum.ReturnStatus.Failure.name());//退款失败
                            log.error(StrUtil.format("订单{}宝付微信退款异常", orderNo), e);

                            order.setExceptionType(OrderException.EB.RefundFailed.name());
                            order.setIsException(YesOrNo.Yes.name());
                            order.setExceptionStatus(YesOrNo.No.name());
                        }

                    } else if (PayEnum.PayWay.Alipay.name().equals(order.getPayWay())) {//退回支付宝

                        //支付宝退款 TODO 需要修改
                        // AlipayTradeRefundResponse refundResponse = null;
                        // try {
                        //     refundResponse = Factory.Payment.Common()
                        //             .refund(outTradeNo, PayUtil.toDoubleAmountStr(returnFee));
                        // } catch (Exception e) {
                        //     order.setExceptionType(OrderException.EB.RefundFailed.name());
                        //     order.setIsException(YesOrNo.Yes.name());
                        //     order.setExceptionStatus(CommonEnum.YesOrNo.NO.name());
                        //
                        //     order.setReturnStatus(OrderEnum.ReturnStatus.FAIL.name());//退款失败
                        //     log.error(StrUtil.format("订单{}支付宝退款错误", orderNo), e);
                        // }
                        //
                        // log.info("支付宝退款：" + cn.hutool.json.JSONUtil.toJsonStr(refundResponse));
                        //
                        // if (!ResponseChecker.success(refundResponse)) {
                        //     log.error(StrUtil.format("订单{}支付宝退款失败", orderNo));
                        // }
                    }


                    //退款成功才记录流水
                    if(StringUtil.equals(order.getReturnStatus(),OrderEnum.ReturnStatus.Success.name())) {
                        //插入用户账单流水：退回余额
                        UserBill userBill = new UserBill();
                        userBill.setComId(order.getComId());
                        userBill.setMemberUserId(order.getMemberUserId());
                        userBill.setNo(OrderUtil.getOrderNo());
                        userBill.setOutTradeNo(outTradeNo);
                        userBill.setOrderNo(orderNo);
                        userBill.setAmount(returnAmount);
                        userBill.setType(FinancialEnum.IncomeOrExpend.Income.name());//收入支出类型：0-收入，1-支出
                        userBill.setEvent(FinancialEnum.UserBillEvent.Refund.name());
                        userBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
                        userBill.setCreateTime(DateUtil.date());
                        userBillService.saveRow(userBill);

                        //插入平台账单流水：充电退回
                        PlatformBill platformBill = new PlatformBill();
                        platformBill.setComId(order.getComId());
                        platformBill.setNo(OrderUtil.getOrderNo());
                        platformBill.setOutTradeNo(outTradeNo);
                        platformBill.setOrderNo(orderNo);
                        platformBill.setAmount(returnAmount);
                        platformBill.setType(FinancialEnum.IncomeOrExpend.Expend.name());//收入支出类型：0-收入，1-支出
                        platformBill.setEvent(FinancialEnum.PlatformBillEvent.OrderRefund.name());
                        platformBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
                        platformBill.setCreateTime(DateUtil.date());
                        platformBillService.saveRow(platformBill);
                    }

                } else {

                    //记录钱包流水，金额为退款金额
                    Wallet memberWallet = new Wallet();
                    memberWallet.setComId(order.getComId());
                    memberWallet.setMemberUserId(order.getMemberUserId());
                    memberWallet.setOrderNo(order.getOrderNo());
                    memberWallet.setNo(OrderUtil.getOrderNo());
                    memberWallet.setType(FinancialEnum.IncomeOrExpend.Income.name());
                    memberWallet.setAmount(returnAmount);
                    memberWallet.setStatus(FinancialEnum.BillStatus.Effective.name());
                    memberWallet.setEvent(FinancialEnum.WalletBillEvent.Refund.name());
                    memberWallet.setCreateTime(DateUtil.date());
                    walletService.saveRow(memberWallet);

                    order.setReturnStatus(OrderEnum.ReturnStatus.Success.name());//退款成功
                    //宝付账户减值todo 只支持全部退款
                    if(order.getIsBaofuSplit()==1 || order.getIsBaofuFireSplit() ==1){
                        baofuRefund(order.getOutTradeNo());
                    }
                }
            }
        }else{
            int serviceFee = orderService.getTimeServiceFee(order,ebOrder.getServicePrice(),chargeSeconds);
            int energyFee =  orderService.getTimeEnergyFee(order,ebOrder.getEnergyPrice());
            //只记录充电金额
            chargeAmount = serviceFee + energyFee;
            order.setChargeAmount(0);//充电金额为0，才不影响其他报表统计
            order.setOrderAmount(0);
            order.setFreeAmount(chargeAmount);//增加免费金额字段来记录充电费用
            ebOrder.setChargeSeconds(chargeSeconds);
            ebOrder.setEndEnergy(endEnergy);
        }


        //查询充电网点的价格
//        Station station = stationService.getRow(order.getDeviceStationId());
//        if (station == null) {
//            log.warn("订单{}网点不存在，忽略佣金分配操作", orderNo);
//            orderService.updateRow(order);
//            ebOrderService.updateRow(ebOrder);
//            return;
//        }
//
//        orderService.updateRow(order);
//        ebOrderService.updateRow(ebOrder);

        // 校验是否进行分佣
        if (!this.isFreeOrder(order)) {
            //分佣计算-邓南辉新版计算方式
            int profit = commissionService.calcCommission(order.getChargeOrderId(), order.getCreateTime(), orderNo, outTradeNo, chargeAmount);

            order.setProfit(profit);
        }

        orderService.updateRow(order);
        ebOrderService.updateRow(ebOrder);

        //删除端口号的订单
        orderRedisTemplate.removeOrder(order.getDeviceCode(),order.getPort());
        orderRedisTemplate.removeChargeFull(order.getChargeOrderId());

        //推送
        pushService.pushChargeEnd(order);

        // 分账
        log.info("订单[{}]开始分账", order.getOrderNo());
        if (YesOrNo.Yes.name().equals(order.getIsProfitSharing())) {
            if(PayEnum.PayWay.Wxpay.name().equals(order.getPayWay())){
                this.wxProfitSharing(order);
            }
        }


    }

//    public static void main(String[] args) {
//       //int chargeAmount = (int) (45 * NumberUtil.div(1800, 3600));
//
//        int time = 610;
//        int diff = time % 1800;
//        int value = diff >= 60 ? time + (1800 - diff) : time - diff;
//
//       System.out.println(value);
//    }

    /**
     * 用户取消充电
     *
     * @param orderNo
     * @return
     */
    public void cancelCharge(String orderNo) throws Exception {
        self.cancelPaidOrder(orderNo, OrderStopReason.EB.USER_CANCEL.name(), true);
    }

    /**
     * 用户停止充电
     *
     * @param orderNo
     * @return
     */
    public void stopCharge(String orderNo) throws Exception {
        self.cancelPaidOrder(orderNo, OrderStopReason.EB.USER_END.name(), false);
    }

    /**
     * 用户停止充电
     *
     * @param orderNo
     * @return
     */
    public void stopChargeByHeart(String orderNo) throws Exception {
        self.cancelPaidOrder(orderNo, OrderStopReason.EB.HEART.name(), true);
    }

    /**
     * 设备离线，用户结束充电
     *
     * @param orderNo
     * @return
     */
    public void stopOfflineCharge(String orderNo) throws Exception {
        self.cancelPaidOrder(orderNo, OrderStopReason.EB.OFFLINE_USER_END.name(), true);
    }

    /**
     * 设备离线，订单超时系统结束充电
     *
     * @param orderNo
     * @return
     */
    public void stopChargeTimeoutCharge(String orderNo) throws Exception {
        self.cancelPaidOrder(orderNo, OrderStopReason.EB.OFFLINE_SYS_END.name(), true);
    }


    public void fullStopCharge(String orderNo) throws Exception {
        self.cancelPaidOrder(orderNo, OrderStopReason.EB.FULLEND.name(), false);
    }

    public void timeEndStopCharge(String orderNo) throws Exception {
        self.cancelPaidOrder(orderNo, OrderStopReason.EB.TIMEEND.name(), false);
    }

    private int getOverPower(String comId,String userId,String stationId,String payWay){
        //不是月卡支付，用最大功率
        if(!StringUtil.equals(payWay,PayEnum.PayWay.MonthCard.name()))
            return 3500;

        CardUser cardUser = cardUserService.getRow(new String[]{"com_id","member_user_id","device_station_id"},new Object[]{comId,userId,stationId});
        if(cardUser != null && DateUtil.betweenDay(new Date(), cardUser.getEndDate(),false) > 0){
            return cardUser.getMaxPower();
        }
        return 3500;
    }



    /**
     * 判断插口是否空闲
     * @param orderId
     * @return
     */
    public  boolean isPortFree(String orderId){
        List<OrderPower> list = orderPowerService.getViewModelList("get_last_order_power_list",OrderPower.class,new Object[]{orderId,5});
        if(list.size() < 5){
            return false;
        }

        boolean portIsFree = true;
        for(OrderPower item : list){
            if(!StringUtil.equals(item.getStatus(), DeviceEnum.PortStatus.Available.name())){
                portIsFree = false;
                break;
            }
        }

        return portIsFree;
    }

    /**
     * 判断是否充满
     * @param orderId
     * @return
     */
   public boolean isChargeFull(String orderId){
       List<OrderPower> list = orderPowerService.getViewModelList("get_last_order_power_list",OrderPower.class,new Object[]{orderId,hshChargingProperties.getChargeFullDuration()});
       if(list.size() < hshChargingProperties.getChargeFullDuration()){
           return false;
       }

       boolean chargeFull = true;
       for(OrderPower item : list){
           if(item.getPower() > hshChargingProperties.getChargeFullPower()){
               chargeFull = false;
               break;
           }
       }

       return chargeFull;
    }


    /**
     * 判断是否计时结束:当设备不上报计时结束超过2分钟，平台自己结束
     * @param order
     * @return
     */
    public boolean isTimeEnd(Order order){
        int paySeconds = order.getPaySeconds();
        Date startTime = order.getCreateTime();
        int chargeSeconds = (int)Math.max(0,(new Date().getTime() - startTime.getTime())/1000);
        if(chargeSeconds - paySeconds >= 120){
            return true;
        }else{
            return false;
        }
    }



    /**
     * 取消已支付未完成订单
     *
     * @param orderNo
     * @param stopReason
     * @param forceStop 是否强行结束或取消订单，不调用设备
     * @throws Exception
     */
    @Lock4j(name = "processPaidOrder", keys = "#orderNo")
    @Transactional
    public void cancelPaidOrder(String orderNo, String stopReason, boolean forceStop) throws Exception {
        // 重新查一遍订单，避免落锁前订单已被改动
        Order order = orderService.getRow("order_no", orderNo);
        if (order == null) {
            throw new ServiceException(OrderCode.NoOrder);
        }

        if (OrderEnum.Status.Completed.name().equals(order.getStatus())) {
            throw new ServiceException(OrderCode.OrderCompleted);
        }

        // 订单记录sysEndType
        order.setEndType(stopReason);
        orderService.updateRow(order);

        Pile pile = pileService.getRow(order.getDevicePileId());
        EbOrder ebOrder = ebOrderService.getRow("charge_order_id",order.getChargeOrderId());

        if (null == pile) { // 设备已被删除，强行结束订单
            log.warn("订单{}充电设备已被删除", order);
            saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.OrderFinish,new Date(),
                    "{}","订单充电设备已被删除");
            self.chargeFinish(orderNo,OrderEnum.Status.Completed, OrderStopReason.EB.SYS_END.name(), false);

            return;
        }

        String deviceName = pile.getImei();
        // 设备离线
        if (!DeviceEnum.DeviceStatus.Online.name().equals(pile.getDeviceStatus())) {
            if (forceStop) {
                Date lastHeartDateTime = getEndTime(order.getChargeOrderId());
                if(lastHeartDateTime == null)
                    lastHeartDateTime = DateUtil.date();

                String tempEndType = OrderStopReason.EB.SYS_END.name();
                if(stopReason.equals(OrderStopReason.EB.OFFLINE_SYS_END.name())){
                    tempEndType =  OrderStopReason.EB.OFFLINE_SYS_END.name();
                }

                setExceptionOrder(order.getChargeOrderId(),OrderException.EB.OfflineStoped);
                saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.OrderFinish,new Date(),
                        "{}","订单充电设备不在线,订单超时或强制结算");
                self.chargeFinish(orderNo,OrderEnum.Status.Completed,tempEndType, false);

            } else {
                log.warn("设备{}不在线，忽略取消订单{}", deviceName, orderNo);
            }
            return;
        }

        //启动未成功
        if(OrderEnum.Status.NotStarted.name().equals(order.getStatus())){
            log.warn("订单{}启动未成功，取消订单,结束类型：{}", orderNo,stopReason);

            setExceptionOrder(order.getChargeOrderId(),OrderException.EB.StartFailed);
            saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.OrderFinish,new Date(),
                    "{}","订单启动未成功，取消订单");
            self.chargeFinish(orderNo,OrderEnum.Status.Failure,stopReason, false);


            return;
        }

        log.debug("stopCharge 订单停充开始");
        //设备停充
        if(forceStop || StringUtil.toInt(order.getRemoteStopCount()) > 0){
            log.warn("远程停止不成功，平台自己停止：{}", orderNo,stopReason);

            setExceptionOrder(order.getChargeOrderId(),OrderException.EB.StopFailed);



            if(StringUtil.toInt(order.getRemoteStopCount()) > 0) {
                Map data = new Hashtable();
                data.put("remote_stop_count",StringUtil.toInt(order.getRemoteStopCount()));
                saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.OrderFinish,new Date(),
                        JSONUtil.toJSONString(data),"远程设备停止不成功，平台自己停止及结算订单");
            }else{
                saveChargeData(order.getComId(),order.getChargeOrderId(), OrderAction.EB.OrderFinish, new Date(),
                        "{}", "平台自己停止及结算订单，停止类型："+OrderStopReason.EB.valueOf(stopReason));
            }

            self.chargeFinish(orderNo, OrderEnum.Status.Completed,stopReason, false);

        }else {

            // 订单记录remote_stop_count为1，如果下次还要停止（设备不回复或停止不了），平台直接结束
            order.setRemoteStopCount(StringUtil.toInt(order.getRemoteStopCount()) + 1);
            orderService.updateRow(order);

//            String command = serviceFactory.getRpcEBDeviceService(pile.getProtocol()).reqStopCharge(order.getOrderNo(), new DeviceKey(pile.getImei()), order.getPort());
//
//            saveChargeData(order.getComId(),order.getChargeOrderId(), OrderAction.EB.StopChargeReq, new Date(), command, String.format("停止类型：%s,是否强制停止：%s",stopReason,forceStop));
//            log.debug("stopCharge 订单停充结束");

            stopDeviceCharge(pile.getProtocol(),order.getComId(),order.getChargeOrderId(),order.getOrderNo(),pile.getImei(),
                    order.getPort(),OrderAction.EB.StopChargeReq, String.format("停止类型：%s,是否强制停止：%s",stopReason,forceStop));
        }
        
    }

    /**
     * 远程停止设备充电
     * @param protocol
     * @param orderId
     * @param orderNo
     * @param imei
     * @param port
     * @param remark
     */
    private void stopDeviceCharge(String protocol,String comId,String orderId,String orderNo,String imei,int port,OrderAction.EB action,String remark){
        RpcEBDeviceService rpcEBDeviceService = serviceFactory.getRpcEBDeviceService(protocol);
        if(rpcEBDeviceService == null){
            throw new ServiceException("设备请重新上电后再尝试！");
        }
        //停充
        String cmd = rpcEBDeviceService.reqStopCharge(orderNo,new DeviceKey(imei),port);

        saveChargeData(comId,orderId, action, new Date(),
                JSONUtil.toJSONString(cmd), remark);
    }

    /**
     * 取消未支付订单
     */
    @Lock4j(name = "processUnpaidOrder", keys = "#orderNo")
    @Transactional
    public void cancelUnpaidOrder(String orderNo) {
        // 重新查一遍订单，避免落锁前订单已被改动
        Order order = orderService.getRow("order_no", orderNo);
        if (order == null) {
            throw new ServiceException(OrderCode.NoOrder);
        }

        if (OrderEnum.Status.Completed.name().equals(order.getStatus())) {
            throw new ServiceException(OrderCode.OrderCompleted);
        }

        if (PayEnum.Status.Payed.name().equals(order.getPayStatus())) {
            throw new ServiceException(OrderCode.Paid);
        }

        Gun updateGun = new Gun();
        updateGun.setDeviceGunId(order.getDeviceGunId());
        updateGun.setOrderNo(StrUtil.EMPTY);
        gunService.updateRow(updateGun);

        Order updateOrder = new Order();
        updateOrder.setChargeOrderId(order.getChargeOrderId());
        updateOrder.setStatus(OrderEnum.Status.Cancel.name());
        updateOrder.setEndType(OrderStopReason.EB.PLATFORM_CANCEL.name());
        orderService.updateRow(updateOrder);

        saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.CancelForUnPay,new Date(),
                "{}","订单超时(60秒)未支付，平台取消订单！");

        // 未付款, 退回优惠券
        if(StrUtil.isNotBlank(order.getActivityCouponsUserId())){
            couponsUserService.returnCouponsUse(order.getActivityCouponsUserId());
        }
    }

    /**
     * 查询订单最后心跳时间
     * @param orderId
     * @return
     */
    private Date getEndTime(String orderId){
        List<OrderPower> list = orderPowerService.getList("charge_order_id",orderId,"create_time","desc");
        if(list.size() > 0){
            OrderPower item = list.get(0);
            return item.getCreateTime();
        }
        return null;
    }




    /**
     * 检查订单是否存在并且属于当前用户
     *
     * @param orderNo
     */
    public void checkUserOrderExits(String orderNo) {
        String userId = userService.get().getMemberUserId();
        Order order = orderService.getEntity(new String[]{"order_no", "member_user_id"}, new Object[]{orderNo, userId});
        if (null == order) {
            throw new ServiceException(OrderCode.NoOrder);
        }
    }

    /**
     * 微信支付回调
     *
     * @param request
     */
    public void wxPayNotify(HttpServletRequest request, String comId) {
        WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = null;
        try {
            wxManager.getPayService(comId);
            wxPayOrderNotifyV3Result = wxPayService.parseOrderNotify(request);
        } catch (WxPayException e) {
            log.error("解析微信支付通知失败", e);
        }

        Order order = orderService.getRow("out_trade_no", wxPayOrderNotifyV3Result.getResult().getOutTradeNo());
        if (null == order) {
            log.error("微信订单" + wxPayOrderNotifyV3Result.getResult().getOutTradeNo() + "不存在！");
            return;
        }
        order.setTransactionId(wxPayOrderNotifyV3Result.getResult().getTransactionId());
        orderService.updateRow(order);

        self.orderPaid(order.getOrderNo(),
                DateUtil.parse(wxPayOrderNotifyV3Result.getResult().getSuccessTime()));
    }

    /**
     * 支付宝支付回调
     * @param request
     * @throws Exception
     */
    public void aliPayNotify(HttpServletRequest request) {

        Map<String, String> parameters = ServletUtil.getParamMap(request);
        log.info("支付宝充电支付回调异步通知：{}", cn.hutool.json.JSONUtil.toJsonStr(parameters));

        boolean verifyResult = false;
        try {
            verifyResult = Factory.Payment.Common().verifyNotify(parameters);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (!verifyResult || !StrUtil.equals("TRADE_SUCCESS", parameters.get("trade_status"))) {
            log.error("支付宝支付异步通知验签未通过！");
        }

        //处理订单支付后续
        String outTradeNo = parameters.get("out_trade_no");
        String payTime = parameters.get("gmt_payment");

        Order order = orderService.getRow("out_trade_no", outTradeNo);
        if (null == order) {
            log.error("支付宝订单{}不存在！", outTradeNo);
            return;
        }

        self.orderPaid(order.getOrderNo(), DateUtil.parse(payTime));
    }

    private String getItemPriceText(FeeEbPrice feePrice){
        //价格(分)
        int payAmount = feePrice.getPrice();
        return (payAmount / 100.0) + "元";
    }

    /**
     * 是否分账
     * @return
     */
    private boolean isProfitSharing(String comId){
        return false;
        //TODO 先关掉分账功能
//        SharingSetting sharingSetting = sharingSettingService.getRow("com_id",comId);
//        if(null == sharingSetting){
//            return false;
//        }
//        return StringUtil.equals(sharingSetting.getProfitSharing(), YesOrNo.Yes.name());
    }

    /**
     * 获取订单剩余时间（秒）
     *
     * @param order
     * @param currentTime
     * @return
     */
//    private int getOrderRemainSeconds(Order order, Date currentTime) {
//        int remainSeconds = order.getPaySeconds();
//        // 订单已开始充电，以当前时间计算剩余时间
//        if (OrderEnum.Status.Charging.name().equals(order.getStatus())) {
//            Date startTime = order.getStartTime();
//            ///int chargeSeconds = (int) DateUtil.between(startTime, currentTime, DateUnit.SECOND, false);
//            remainSeconds = remainSeconds - (int)Math.max(0,(currentTime.getTime() - startTime.getTime())/1000);
//        }
//        return Math.max(0, remainSeconds);
//    }

    /**
     * 获取订单充电时间（秒）
     *
     * @param order
     * @param currentTime
     * @return
     */
    public int getOrderChargeSeconds(Order order, Date currentTime) {
        int paySeconds = order.getPaySeconds();
        Date startTime = order.getCreateTime();
        int chargeSeconds = (int)Math.max(0,(currentTime.getTime() - startTime.getTime())/1000);
        return Math.min(paySeconds, chargeSeconds);

    }

    /**
     * 查询在线充电时长（秒）
     * @param order
     * @return
     */
    private Integer getOnlineChargeSeconds(Order order){
        List<OrderPower> list = orderPowerService.getViewModelList("get_last_order_power_list",OrderPower.class,new Object[]{order.getChargeOrderId(),1});
        if(list.size() > 0){
            return StringUtil.toInt(list.get(0).getTime());
        }else {
            return getOrderChargeSeconds(order,new Date());
        }
    }

    /**
     * 不满30分钟，按30分钟收费,当秒数超过60，才才会加30分钟
     *
     * @param time
     * @return
     */
    private int getCeilTime(int time) {
        int diff = time % 1800;
        return diff >= 60 ? time + (1800 - diff) : time - diff;
    }

    /**
     * 是否是免费充电订单
     * @param order
     * @return
     */
    public boolean isFreeOrder(Order order){
        return YesOrNo.Yes.name().equals(order.getIsFree());
    }

    /**
     * 保存记录订单操作日志
     * @param orderId 订单ID
     * @param action 操作类型
     * @param time 时间
     * @param data 其他数据
     * @param remark 描述
     */
    public void saveChargeData(String comId, String orderId, OrderAction.EB action, Date time, Object data, String remark){
        DataLog dataLog = new DataLog();
        dataLog.setComId(comId);
        dataLog.setChargeOrderId(orderId);
        dataLog.setAction(action.name());
        dataLog.setActionZh(action.getValue());
        dataLog.setCreateTime(time);
        dataLog.setJsonData(cn.hutool.json.JSONUtil.toJsonStr(data));
        dataLog.setRemark(remark);
        dataLogService.saveRow(dataLog);
    }

    /**
     * 微信分账
     * @param order
     */
    public void wxProfitSharing(Order order){
        List<Receiver> list = receiverService.getRows("com_id",order.getComId());
        if(null == list || list.size() == 0){
            log.error("分账失败，未设置分账收款用户！");
            return;
        }

        SharingSetting sharingSetting = sharingSettingService.getRow("com_id",order.getComId());
        if(null == sharingSetting){
            log.error("分账失败，未设置分账金额比例！");
            return;
        }

        int rate = StringUtil.toInt(sharingSetting.getSharingRate());
        long amount = (order.getPayAmount() - order.getReturnAmount()) * rate / 100;
        if(amount <= 0){
            log.error("分账金额小于0，跳过分账！");
            return;
        }

        Receiver receiverMap = list.get(RandomUtil.randomInt(0, list.size()));
        String account = StringUtil.getTrim(receiverMap.getAccount());
        ProfitSharingReceiver receiver = new ProfitSharingReceiver(StringUtil.getTrim(receiverMap.getType()),
                account, amount, "分账");

        String outTradeNo = OrderUtil.getWxOrderNo();
        order.setProfitSharingOutTradeNo(outTradeNo);

        ProfitSharingRequest req = new ProfitSharingRequest();
        req.setAppid(wxManager.getPayService(order.getComId()).getConfig().getAppId());
        req.setTransactionId(StringUtil.getTrim(order.getTransactionId()));
        req.setOutOrderNo(outTradeNo);
        req.setUnfreezeUnsplit(true);
        req.setReceivers(ListUtil.toList(receiver));
        ProfitSharingResult result = null;
        try {
            result = wxSharingService.profitSharing(req);
        } catch (Exception e) {
            log.error("分账错误！", e);
            order.setProfitSharingStatus(OrderEnum.ProfitSharingStatus.FAIL.name());
            orderService.updateRow(order);
            return;
        }
        log.info("分账结果：{}", cn.hutool.json.JSONUtil.toJsonStr(result));
        // TODO 检查一下同步返回的结果是否分账已完成，如果是处理中做个定时任务查询分账结果

        order.setProfitSharingStatus(result.getState());
        orderService.updateRow(order);

        ProfitSharingResult.Receiver receiverResult = result.getReceivers().stream()
                .filter(item -> item.getAccount().equals(account)).findFirst().get();

        Records sharingRecords = new Records();
        sharingRecords.setComId(order.getComId());
        sharingRecords.setMemberUserId(receiverMap.getMemberUserId());
        sharingRecords.setChargeOrderId(order.getChargeOrderId());
        sharingRecords.setAccount(account);
        sharingRecords.setOutTradeNo(outTradeNo);
        sharingRecords.setSharingAmount((int) amount);
        sharingRecords.setSharingRate(rate);
        sharingRecords.setSharingDate(DateUtil.date());
        sharingRecords.setSharingStatus(receiverResult.getResult());
        sharingRecords.setSharingFailReason(receiverResult.getFailReason());
        recordsService.saveRow(sharingRecords);

    }

    /**
     * 记录跳档
     * @param orderId 订单ID
     * @param power 原功率表
     * @param skipPower 跳档功率
     * @param startPower 档位开始功率
     * @param endPower 档位截止功率
     * @param price 单价：(分/小时）
     */
    private void recordSkipPower(String comId,String orderId,int power,int skipPower,int startPower,int endPower,int price, EBPort port){
        OrderSkipPower record = new OrderSkipPower();
        record.setComId(comId);
        record.setChargeOrderId(orderId);
        record.setPower(power);
        record.setSkipPower(skipPower);
        record.setStartPower(startPower);
        record.setEndPower(endPower);
        record.setPrice(price);
        record.setCreateTime(new Date());
        orderSkipPowerService.saveRow(record);

        saveChargeData(comId,orderId,OrderAction.EB.SlipPower,new Date(),
                JSONUtil.toJSONString(port),
                "功率从"+power+"瓦跳到"+skipPower+"瓦，当前："+startPower+"~"+endPower+"，服务费单价："+(price/100.0)+"(元/小时)");

    }

    /**
     * 功率变大，调整服务费收费功率档位
     *
     * @param order 订单
     * @param power   最大功率
     */
    public void adjustOrderPower(Order order,EbOrder ebOrder, Integer power,Integer outTime, EBPort port) throws Exception {

        //TODO PRICE

        // 功率超出当前收费最大功率，重新计算充电单价和充电时长
        OrderEbPower orderEbPower = orderEbPowerService.getViewModel("get_eb_fee_power_by_power",OrderEbPower.class, new Object[]{order.getChargeOrderId(),order.getComId(), power, power});
        int oldPower = ebOrder.getChargePower();

        Pile pile = pileService.getRow(order.getDevicePileId());
        if (pile == null) { // 设备已被删除
            log.warn("订单{}充电设备已被删除", order);
            return;
        }



        // 超出价格表范围
        if (orderEbPower == null && ebOrder != null) {
            ebOrder.setChargePower(port.getPower().intValue());
            order.setEndType(OrderStopReason.EB.POWER_OVERLOAD.name());

            ebOrderService.updateRow(ebOrder);
            orderService.updateRow(order);

            //停充
            String command = serviceFactory.getRpcEBDeviceService(pile.getProtocol()).reqStopCharge(IdUtils.getPrimaryKey(),new DeviceKey(pile.getImei()),port.getPort());

            saveChargeData(order.getComId(),order.getChargeOrderId(), OrderAction.EB.StopChargeReq, new Date(),
                    command, "订单已超出最大允许功率，费率表中未查到适合的费率信息");
            return;
        }

        // 重新计算充电时长
        int newStartPower = orderEbPower.getStartPower();
        int newEndPower = orderEbPower.getEndPower();
        int newPrice = orderEbPower.getPrice();

        if(newPrice <= 0){
            log.warn("订单{}功率设置为0，不能调整价格", order);
            return;
        }

        //新计费方式：仅修改功率档位、服务费价格
        ebOrder.setServicePrice(newPrice);
        ebOrder.setChargePower(power);
        ebOrder.setStartPower(newStartPower);
        ebOrder.setEndPower(newEndPower);
        ebOrder.setEndEnergy(port.getEnergy());
        ebOrderService.updateRow(ebOrder);
        recordSkipPower(order.getComId(),order.getChargeOrderId(),oldPower,power,newStartPower,newEndPower,newPrice,port);

        //充满自停或免费充电：不需要调整时间，只需要修改当前功率的档次
//        if(isFreeOrder(order)){
//            // 保存新信息
//            ebOrder.setPowerPrice(newPrice);
//            ebOrder.setChargePower(power);
//            ebOrder.setStartPower(newStartPower);
//            ebOrder.setEndPower(newEndPower);
//            ebOrderService.updateRow(ebOrder);
//
//            recordSkipPower(order.getComId(),order.getChargeOrderId(),oldPower,power,newStartPower,newEndPower,newPrice,port);
//            return;
//        }



//        int payAmount = order.getPayAmount();
//        int newPaySeconds = (int) NumberUtil.mul(NumberUtil.div(3600, newPrice), payAmount);
//
//        //已充电时长
//        int chargeSeconds = getOrderChargeSeconds(order, DateUtil.date());
//        // 新时长-已充时长=剩余时长
//        int seconds = newPaySeconds - chargeSeconds;
//        if (seconds > 0) {
//            //int totalSeconds = StringUtil.toInt(order.get("total_seconds"));
//
//            //修改为设备反馈成功再改订单数据
//            OrderSkip orderSkip = new OrderSkip();
//            orderSkip.setPaySeconds(newPaySeconds);
//            orderSkip.setChargeOrderId(order.getChargeOrderId());
//            orderSkip.setComId(order.getComId());
//            orderSkip.setChargePower(power);
//            orderSkip.setPowerPrice(newPrice);
//            orderSkip.setStartPower(newStartPower);
//            orderSkip.setEndPower(newEndPower);
//            orderSkip.setTotalSeconds(chargeSeconds);//每次跳档记录的总时长（秒）
//            orderSkipService.saveRow(orderSkip);
//
//            recordSkipPower(order.getComId(),order.getChargeOrderId(),oldPower,power,newStartPower,newEndPower,newPrice,port);
//
//            RpcEBDeviceService rpcEBDeviceService = serviceFactory.getRpcEBDeviceService(pile.getProtocol());
//            if(rpcEBDeviceService == null){
//                throw new ServiceException("设备请重新上电后再尝试！");
//            }
//
//            //磐众设备不支持修改时间，只能系统自己修改，系统自动判断计时结束
//            if(StringUtil.equals(pile.getProtocol(),DeviceProtocolEnum.PZ_MQTT_10.getKey())){
//                order.setPaySeconds(orderSkip.getPaySeconds());
//                orderService.updateRow(order);
//
//                ebOrder.setChargePower(orderSkip.getChargePower());
//                ebOrder.setPowerPrice(orderSkip.getPowerPrice());
//                ebOrder.setStartPower(orderSkip.getStartPower());
//                ebOrder.setEndPower(orderSkip.getEndPower());
//                ebOrder.setTotalSeconds(orderSkip.getTotalSeconds());//每次跳档记录的总时长（秒）
//                ebOrderService.updateRow(ebOrder);
//
//                orderSkipService.delete(orderSkip.getChargeOrderSkipId());
//
//                saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.SlipPower,new Date(),"","更新充电时长成功，新总时长："+orderSkip.getPaySeconds()+"秒");
//
//            }else {
//                // 重新以下单通知设备更改订单
//                if (StringUtil.equals(pile.getProtocol(), DeviceProtocolEnum.YD_SDK_10.getKey())) {
//
//                    String cmd = serviceFactory.getRpcEBDeviceService(pile.getProtocol()).reqUpdateCharge(order.getOrderNo(),new DeviceKey(pile.getImei()),port.getPort(),newPaySeconds,
//                            getOverPower(order.getComId(),order.getMemberUserId(),order.getDeviceStationId(),order.getPayWay()));
//                    saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.RestartChargeReq,new Date(),
//                            cmd,"重新计算时长并下单，新时长："+seconds+"秒");
//                } else {
//                    String cmd = serviceFactory.getRpcEBDeviceService(pile.getProtocol()).reqUpdateCharge(order.getOrderNo(),new DeviceKey(pile.getImei()),port.getPort(),seconds,
//                            getOverPower(order.getComId(),order.getMemberUserId(),order.getDeviceStationId(),order.getPayWay()));
//                    saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.RestartChargeReq,new Date(),
//                            cmd,"重新计算时长并下单，新时长："+seconds+"秒");
//                }
//            }
//        } else {
//            ebOrder.setPowerPrice(newPrice);
//            ebOrderService.updateRow(ebOrder);
//
//            order.setEndType(OrderStopReason.EB.POWER_LACK_BALANCE.name());
//            orderService.updateRow(order);
//
//            // 剩余时长小于0，通知设备结束订单
//            String command = serviceFactory.getRpcEBDeviceService(pile.getProtocol()).reqStopCharge(order.getOrderNo(),new DeviceKey(pile.getImei()),port.getPort());
//
//            saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.StopChargeReq,new Date(),
//                    command,"重新计算时长,剩余时长小于0秒，通知设备结束订单");
//        }

    }

    /**
     * 查询当前时段的电费+服务费
     * @param orderId
     * @return
     */
    public OrderEbTime getCurrentEbTime(String orderId){
        String dateStr = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN) + " ";
        Date currentTime = DateUtil.parse(DateUtil.format(new Date(),DatePattern.NORM_DATETIME_PATTERN));

        OrderEbTime currentFeeTime = null;
        List<OrderEbTime> timeList = orderEbTimeService.getRows("charge_order_id",orderId);
        for(OrderEbTime item : timeList){
            Date startTime = DateUtil.parse(dateStr + item.getStartTime());
            Date endTime = DateUtil.parse(dateStr + item.getEndTime());
            if(currentTime.getTime() >= startTime.getTime() && currentTime.getTime() <= endTime.getTime()){
                currentFeeTime = item;
                break;
            }
        }

        return currentFeeTime;
    }

    /**
     * 电费+服务费按时间收费计价
     * @param order 订单
     * @param ebOrder 电量
     */
    public void adjustOrderTime(Order order, EbOrder ebOrder,EBPort ebPort){


        //判断余额是否用完
        int energyFee = orderService.getTimeEnergyFee(order,ebOrder.getEnergyPrice());
        int serviceFee = orderService.getTimeServiceFee(order,ebOrder.getServicePrice(),getOnlineChargeSeconds(order));
        //非月卡和非免费订单才需要判断余额是否结束
        if (StringUtil.equals(order.getIsMonth(),YesOrNo.No.name()) && StringUtil.equals(order.getIsFree(),YesOrNo.No.name()) &&
                (energyFee + serviceFee) >= order.getPayAmount()) {
            log.info("电费：{},服务费:{}",energyFee,serviceFee);
            if (!StringUtil.isEmpty(order.getEndType())) {//说明已经下发过，不再下发
                return;
            }

            Order updateOrder = new Order();
            updateOrder.setChargeOrderId(order.getChargeOrderId());
            updateOrder.setEndType(OrderStopReason.EB.NO_BALANCE.name());
            orderService.updateRow(updateOrder);

            Pile pile = pileService.getRow(order.getDevicePileId());
            if(pile == null)
                return;
            stopDeviceCharge(pile.getProtocol(),order.getComId(), order.getChargeOrderId(),order.getOrderNo(),
                    pile.getImei(), order.getPort(), OrderAction.EB.NotBalanceStopChargeReq, "余额已用完，计费结束！");
        }else{

            Order updateOrder = new Order();
            updateOrder.setChargeOrderId(order.getChargeOrderId());
            updateOrder.setEnergyFee(energyFee);
            updateOrder.setServiceFee(serviceFee);
            updateOrder.setChargeCapacity(orderService.getCapacity(order.getChargeOrderId()));
            updateOrder.setChargeAmount(energyFee + serviceFee);
            updateOrder.setOrderAmount(energyFee + serviceFee);
            updateOrder.setDuration(getOrderChargeSeconds(order,new Date()));
            orderService.updateRow(updateOrder);


            ebOrder.setChargeSeconds(getOrderChargeSeconds(order,new Date()));
            ebOrder.setEnergyFee(energyFee);
            ebOrder.setServiceFee(serviceFee);
            ebOrder.setChargeCapacity(updateOrder.getChargeCapacity());
            ebOrder.setCurrentPower(StringUtil.toInt(ebPort.getPower()));
            ebOrderService.updateRow(ebOrder);
        }
    }

    /**
     * 电费计费
     * @param order 订单
     * @param energy 电量
     */
    public void adjustOrderEnergy(Order order, long energy){
        List<OrderEnergy> energyList = orderEnergyService.getRows("charge_order_id",order.getChargeOrderId(),"create_time","asc");
        String dateStr = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN) + " ";

        OrderEnergy currentTimeEnergy = null;

        Date currentTime = DateUtil.parse(DateUtil.format(new Date(),DatePattern.NORM_DATETIME_PATTERN));
        for(OrderEnergy item : energyList){
            Date startTime = DateUtil.parse(DateUtil.format(item.getCreateTime(), DatePattern.NORM_DATE_PATTERN)  + " "+ item.getStartTime()+":00");
            Date endTime = DateUtil.parse(DateUtil.format(item.getCreateTime(), DatePattern.NORM_DATE_PATTERN)  + " "+ item.getEndTime()+":00");
            if(currentTime.getTime() >= startTime.getTime() && currentTime.getTime() <= endTime.getTime()){
                currentTimeEnergy = item;
                break;
            }
        }

        if(currentTimeEnergy == null){//如果还没有则新建一个时段的电费
            currentTimeEnergy = new OrderEnergy();

            OrderEbTime currentFeeTime = null;
            List<OrderEbTime> timeList = orderEbTimeService.getRows("charge_order_id",order.getChargeOrderId());
            for(OrderEbTime item : timeList){
                Date startTime = DateUtil.parse(dateStr + item.getStartTime()+":00");
                Date endTime = DateUtil.parse(dateStr + item.getEndTime()+":00");
                if(currentTime.getTime() >= startTime.getTime() && currentTime.getTime() <= endTime.getTime()){
                    currentFeeTime = item;
                    break;
                }
            }

            if(currentFeeTime == null){
                log.error("没有对应的时段电费，订单号:{},时段电费:{},时段电量:{}",order.getOrderNo(),timeList,energyList);
                return;
            }

            OrderEnergy beforeTimeEnergy = orderEnergyService.getViewModel("get_before_energy_time",OrderEnergy.class,new Object[]{order.getComId(),order.getChargeOrderId()});

            currentTimeEnergy.setChargeOrderId(order.getChargeOrderId());
            currentTimeEnergy.setComId(order.getComId());
            currentTimeEnergy.setStartTime(currentFeeTime.getStartTime());
            currentTimeEnergy.setEndTime(currentFeeTime.getEndTime());
            currentTimeEnergy.setPrice(currentFeeTime.getPrice());
            currentTimeEnergy.setServiceFee(currentFeeTime.getServiceFee());
            currentTimeEnergy.setStartEnergy(beforeTimeEnergy == null ? energy : beforeTimeEnergy.getEndEnergy());
            currentTimeEnergy.setEndEnergy(energy);
            currentTimeEnergy.setCreateTime(new Date());
            currentTimeEnergy.setChargeStartTime(new Date());
            currentTimeEnergy.setChargeEndTime(new Date());

        }else{
            if(energy > currentTimeEnergy.getEndEnergy()) {
                currentTimeEnergy.setEndEnergy(energy);
            }
            currentTimeEnergy.setChargeEndTime(new Date());
        }

        orderEnergyService.saveRow(currentTimeEnergy);

        Pile pile = pileService.getRow(order.getDevicePileId());
        if(pile == null)
            return;

        //超过12小时，判断为已充满
        if(orderService.getOrderChargeSeconds(order,new Date()) >= 12 * 3600){
            if(!StringUtil.isEmpty(order.getEndType())){//说明已经下发过，不再下发
                return;
            }

            Order updateOrder = new Order();
            updateOrder.setChargeOrderId(order.getChargeOrderId());
            updateOrder.setEndType(OrderStopReason.EB.FULLEND.name());
            orderService.updateRow(updateOrder);

            stopDeviceCharge(pile.getProtocol(),order.getComId(), order.getChargeOrderId(),order.getOrderNo(),
                    pile.getImei(), order.getPort(), OrderAction.EB.FullStopChargeReq,"充电超过12小时间，判断为充满自停");
        }

        int energyFee = orderService.getEnergyFee(order.getChargeOrderId());
        int serviceFee = orderService.getServiceFee(order.getChargeOrderId());

        Order updateOrder = new Order();
        updateOrder.setChargeOrderId(order.getChargeOrderId());
        updateOrder.setEnergyFee(energyFee);
        updateOrder.setServiceFee(serviceFee);
        updateOrder.setChargeCapacity(orderService.getCapacity(order.getChargeOrderId()));
        updateOrder.setChargeAmount(energyFee + serviceFee);
        updateOrder.setOrderAmount(energyFee + serviceFee);
        updateOrder.setDuration(orderService.getOrderChargeSeconds(order,new Date()));
        orderService.updateRow(updateOrder);


        //更新最新的电费及服务费单价
        EbOrder ebOrder = ebOrderService.getRow("charge_order_id",order.getChargeOrderId());
        ebOrder.setEnergyPrice(currentTimeEnergy.getPrice());
        ebOrder.setServicePrice(currentTimeEnergy.getServiceFee());
        ebOrder.setChargeSeconds(orderService.getOrderChargeSeconds(order,new Date()));
        ebOrder.setEnergyFee(energyFee);
        ebOrder.setServiceFee(serviceFee);
        ebOrder.setChargeCapacity(updateOrder.getChargeCapacity());
        ebOrderService.updateRow(ebOrder);

        if(YesOrNo.Yes.name().equals(order.getIsFree()))
            return;

        //判断余额是否用完
        if ((energyFee + serviceFee) >= order.getPayAmount()) {
            if (!StringUtil.isEmpty(order.getEndType())) {//说明已经下发过，不再下发
                return;
            }

            Order stopUpdateOrder = new Order();
            stopUpdateOrder.setChargeOrderId(order.getChargeOrderId());
            stopUpdateOrder.setEndType(OrderStopReason.EB.NO_BALANCE.name());
            orderService.updateRow(stopUpdateOrder);
            stopDeviceCharge(pile.getProtocol(),order.getComId(), order.getChargeOrderId(),order.getOrderNo(),
                    pile.getImei(), order.getPort(), OrderAction.EB.NotBalanceStopChargeReq, "余额已用完，计费结束！");
        }
    }



    /**
     * 更新充电最大功率
     *
     * @param order 订单
     * @param power 实时功率
     */
    public void adjustOrderMaxPower(Order order, int power) {
        EbOrder ebOrder = ebOrderService.getRow("charge_order_id",order.getChargeOrderId());
        if(ebOrder != null) {
            int chargePower = ebOrder.getChargePower();
            ebOrder.setTempMaxPower(0);
            ebOrder.setTempPowerNum(0);

            if(power > chargePower){
                ebOrder.setChargePower(power);
            }

            ebOrderService.updateRow(ebOrder);
        }

    }

    /**
     * 更新实时充电秒数
     *
     * @param order         订单
     * @param chargeSeconds 充电时间
     */
    public void updateChargeSecondsAndPower(Order order, int chargeSeconds,int power) {

//        EbOrder ebOrder = ebOrderService.getRow("charge_order_id",order.getChargeOrderId());
//        if(ebOrder != null) {
//            //int totalSeconds = ebOrder.getTotalSeconds();
//
//            //实时计算金额
//            int duration = getOrderChargeSeconds(order, DateUtil.date());
//            int feeChargeDuration = 0;
//            if (duration >= 300) { //充电满5分钟才收费
//                feeChargeDuration = getCeilTime(duration); //按30分钟取整
//                feeChargeDuration = Math.min(order.getPaySeconds(), feeChargeDuration); //不能大于支付时长
//            }
//
//            int payAmount = order.getPayAmount();
//            double price = payAmount * 1.0 / order.getPaySeconds();
//
//            int chargeAmount = 0;
//            if (feeChargeDuration >= order.getPaySeconds()) {
//                chargeAmount = payAmount;
//            } else {
//                chargeAmount = (int) (feeChargeDuration * price);
//                chargeAmount = Math.min(chargeAmount, payAmount);//不能大于支付金额
//            }
//
//            log.info("心跳计费金额：{}，充电时长：{}，单价：{}",chargeAmount,feeChargeDuration,price);
//            order.setDuration(duration);
//            order.setChargeAmount(chargeAmount);
//            order.setOrderAmount(chargeAmount);
//
//            ebOrder.setChargeSeconds(chargeSeconds);
//            ebOrder.setCurrentPower(power);
//
//
//            orderService.updateRow(order);
//            ebOrderService.updateRow(ebOrder);
//        }
    }

    /**
     * 开启充电，设备没有回调，需要修复单的状态为充电中
     *
     * @param port
     */
    public void fixNotStartOrder(Order order,EBPort port) {
        order.setStatus(OrderEnum.Status.Charging.name());
        orderService.saveRow(order);

        //记录订单缓存
        orderRedisTemplate.removeOrder(order.getDeviceCode(),order.getPort());
        orderRedisTemplate.setOrder(order.getDeviceCode(),order.getPort(),OrderEnum.Status.Charging,order.getChargeOrderId());

        saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.FixOrderCharging,new Date(),
                JSONUtil.toJSONString(port),"开启充电设备没有回调通知，修复订单状态为：充电中");

    }

    /**
     * 记录为异常订单
     * @param orderId
     * @param exception
     */
    public void setExceptionOrder(String orderId, OrderException.EB exception){
        Order order = new Order();
        order.setChargeOrderId(orderId);
        order.setExceptionStatus(YesOrNo.No.name());
        order.setIsException(YesOrNo.Yes.name());
        order.setExceptionType(exception.name());
        orderService.updateRow(order);
    }


    /**
     * 查询端口正在充电中订单
     * @param deviceCode
     * @param port
     * @return
     */
    public Order getChargingOrder(String deviceCode, Integer port){
        List<Order> list = orderService.getRows(new String[]{"device_code","port","status"},new Object[]{deviceCode,port,OrderEnum.Status.Charging.name()},
                "create_time","desc");
        if(list.size() > 0)
            return list.get(0);
        else
            return null;
    }


    /*************************************************************************以下是RPC 回调的业务方法****************************************/

    /**
     * 上报刷卡充电
     * @param seq 序列号
     * @param imei IMEI码
     * @param cardNo 卡号
     * @param money 卡上金额-可不用
     * @param port 端口
     */
    @Override
    public void reqSlotCard(String cmd, String seq, String imei,String protocol,String cardNo,Integer money,Integer port){

    }

    /**
     * 上报投币充电
     *
     * @param seq        序列号
     * @param imei IMEI码
     * @param port       端口
     * @param coinNum    硬件数量
     */
    @Override
    public void reqInsertCoin(String cmd, String seq, String imei, String protocol,Integer port, Integer coinNum) {

    }

    /**
     * 设备端口上报
     *
     * @param seq        序列号
     * @param imei IMEI码
     * @param ports      端口列表
     */
    @Override
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void reqPortsNotify(String cmd, String seq, String imei, String protocol,List<EBPort> ports) {

        serviceFactory.getRpcEBDeviceService(protocol).respPortsNotify(seq,new DeviceKey(imei));

        Pile pile = pileService.getRow("imei",imei);
        if(pile == null)
            return;

        //当comId为空时，属于厂商测试，不需要处理数据
        if(StringUtil.isEmpty(pile.getComId()))
            return;

        for(EBPort port : ports){
            //记录订单实时数据
            Order order = getChargingOrder(pile.getCode(), port.getPort());
            log.info("socketNotify order:{}", order);
            if(order != null && !port.getState().equals(DeviceEnum.PortStatus.Charging.name())){

                //再次检查订单状态，防止有并发进入，本方法未加锁
                order = orderService.getRow("order_no", order.getOrderNo());
                if (OrderEnum.Status.Completed.name().equals(order.getStatus())) {
                    log.warn("订单{}已结束，忽略socketNotify", order.getOrderNo());
                    continue;
                }

                OrderStopReason.EB stopReason = OrderStopReason.EB.valueOf(port.getReason());

                //当是欣华协议的话，需要通过有没有心跳数据来判断是未插插头还是插头已拔出
                if(pile.getProtocol().equals(DeviceProtocolEnum.XH_TCP_10.getKey())){
                    OrderPower orderPower = orderPowerService.getRow(new String[]{"com_id","charge_order_id"},new Object[]{order.getComId(),order.getChargeOrderId()});
                    if(orderPower == null && stopReason == OrderStopReason.EB.BREAK){
                        stopReason = OrderStopReason.EB.NO_LOAD;
                    }
                }

                saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.DeviceStopChargeReq,new Date(),
                        cmd,"设备通知停止充电，停止类型："+(stopReason != null ? stopReason.getValue() : port.getState()));

                self.chargeFinish(order.getOrderNo(),OrderEnum.Status.Completed,port.getReason(), false);

                saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.OrderFinish,new Date(),
                        cmd,"正常结算");



            }

//            //告警记录
//            if(pile != null && port.getState().equals(DeviceEnum.PortStatus.Faulted.name())){
//
//                PortAlarmRecord record = new PortAlarmRecord();
//                record.setDevicePileId(pile.getDevicePileId());
//                record.setCode(pile.getCode());
//                record.setDeviceName(pile.getImei());
//                record.setGunNum(port.getPort());
//                //record.setAlarmCode(port.getState());
//                record.setCreateTime(new Date());
//                record.setComId(pile.getComId());
//                alarmRecordService.saveRow(record);
//
//                //TODO 推送
//
//            }
        }
    }

    /**
     * 回复开始充电
     *
     * @param seq        序列号
     * @param imei IMEI码
     * @param port       端口
     * @param ports      端口列表
     */
    @Override
    @Transactional
    public void respStartCharge(String cmd, String seq, String imei, Integer port, List<EBPort> ports) {

        //当comId为空时，属于厂商测试，不需要处理数据
        Pile devicePile = pileService.getRow("imei",imei);
        if(devicePile == null || StringUtil.isEmpty(devicePile.getComId()))
            return;

        // 启动成功，订单更新状态
        Order order = orderService.getRow(new String[]{"device_imei","port","status","pay_status"},new Object[]{imei,port,OrderEnum.Status.NotStarted.name(),PayEnum.Status.Payed.name()});
        if(order != null) {

            EBPort ebPort = null;
            for(EBPort item : ports){
                if(item.getPort() == port && item.getState().equals(DeviceEnum.PortStatus.Charging.name())){
                    ebPort = item;
                    break;
                }
            }

            if(ebPort != null) {
                log.debug("startChargeResp 订单开始");

                //更新设备充电口状态
                Gun gun = gunService.getRow(order.getDeviceGunId());
                if (gun != null) {
                    gun.setStatus(DeviceEnum.PortStatus.Charging.name()); //充电中
                    gunService.updateRow(gun);
                }

                order.setStatus(OrderEnum.Status.Charging.name());
                if(order.getStartTime() == null) {
                    order.setStartTime(new Date());
                }
                orderService.updateRow(order);

                EbOrder ebOrder = ebOrderService.getRow("charge_order_id",order.getChargeOrderId());
                if(ebOrder != null){
                    if(StringUtil.toInt(ebPort.getPower()) > StringUtil.toInt(ebOrder.getChargePower())) {
                        ebOrder.setChargePower(StringUtil.toInt(ebPort.getPower()));
                    }
                    if(ebOrder.getBeginEnergy() == null && StringUtil.toLong(ebPort.getEnergy()) > 0) {
                        ebOrder.setBeginEnergy(StringUtil.toLong(ebPort.getEnergy()));
                    }
                    ebOrderService.updateRow(ebOrder);
                }

                //记录订单缓存
                orderRedisTemplate.removeOrder(order.getDeviceCode(),order.getPort());
                orderRedisTemplate.setOrder(order.getDeviceCode(),order.getPort(),OrderEnum.Status.Charging,order.getChargeOrderId());


                saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.StartChargeResp,new Date(),cmd,"设备回复开始充电成功");
            }
        }else{
            //欣华的订单更新充时时间的处理逻辑
            Order chargeOrder = orderService.getRow(new String[]{"device_imei","port","status"},new Object[]{imei,port,OrderEnum.Status.Charging.name()});
            if(chargeOrder != null){
                handleUpdateChargeOrder(chargeOrder);
            }
        }
    }

    /**
     * 回复更新充电时间
     * @param seq 序列号
     * @param imei IMEI码
     * @param port 端口
     * @param ports 端口列表
     */
    @Override
    @Transactional
    public void respUpdateCharge(String command,String seq, String imei,Integer port, List<EBPort> ports){

        //当comId为空时，属于厂商测试，不需要处理数据
        Pile devicePile = pileService.getRow("imei",imei);
        if(StringUtil.isEmpty(devicePile.getComId()))
            return;
        Order order = getChargingOrder(devicePile.getCode(), port);
        if(order != null) {
            handleUpdateChargeOrder(order);
        }
    }

    /**
     * 回复结束充电
     *
     * @param seq        序列号
     * @param imei IMEI码
     * @param port       端口
     * @param ports      端口列表
     */
    @Override
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void respStopCharge(String cmd, String seq, String imei, Integer port, List<EBPort> ports) {
        log.debug("respStopCharge 结束充电, seq-{}", cmd);

        //当comId为空时，属于厂商测试，不需要处理数据
        Pile devicePile = pileService.getRow("imei",imei);
        if(devicePile == null || StringUtil.isEmpty(devicePile.getComId()))
            return;

        log.info("respStopCharge:{}",JSONUtil.toJSONString(cmd));
        Order order = getChargingOrder(devicePile.getCode(), port);;
        if(order != null) {

            EBPort ebPort = null;
            for(EBPort item : ports){
                if(item.getPort() == port){
                    ebPort = item;
                    break;
                }
            }

            if(ebPort != null && !ebPort.getState().equals(DeviceEnum.PortStatus.Charging.name())) {

                //再次检查订单状态，防止有并发进入，本方法未加锁
                order = orderService.getRow("order_no", order.getOrderNo());
                if (OrderEnum.Status.Completed.name().equals(order.getStatus())) {
                    log.warn("订单{}已结束，忽略stopCharge", seq);
                    return;
                }

                log.debug("stopCharge 订单结算开始");
                saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.StopChargeResp,new Date(),cmd,"设备回复停止充电成功");

                //String orderNo = StringUtil.getTrim(order.get("order_no"));
                String endType = OrderStopReason.EB.USER_END.name();
                if(OrderStopReason.EB.ADMIN_END.name().equals(order.getEndType()))
                    endType = OrderStopReason.EB.ADMIN_END.name();

                //EbOrder ebOrder = ebOrderService.getRow("charge_order_id",order.getChargeOrderId());
                self.chargeFinish(order.getOrderNo(),OrderEnum.Status.Completed, endType, false);

                saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.OrderFinish,new Date(),cmd,"正常结算");

            }
        }
    }

    /**
     * 处理更新订单时间的逻辑:暂不使用
     * @param order
     */
    private void handleUpdateChargeOrder(Order order){
        OrderSkip skipOrder = orderSkipService.getRow(new String[]{"com_id","charge_order_id"},new String[]{order.getComId(),order.getChargeOrderId()});
        EbOrder ebOrder = ebOrderService.getRow(new String[]{"com_id","charge_order_id"},new String[]{order.getComId(),order.getChargeOrderId()});
        if(ebOrder == null || skipOrder == null){
            saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.SlipPower,new Date(),"","ebOrder或skipOrder为空，保存失败！");
            return;
        }

        order.setPaySeconds(skipOrder.getPaySeconds());
        orderService.updateRow(order);

        ebOrder.setChargePower(skipOrder.getChargePower());
        ebOrder.setServicePrice(skipOrder.getPowerPrice());
        ebOrder.setStartPower(skipOrder.getStartPower());
        ebOrder.setEndPower(skipOrder.getEndPower());
        ebOrder.setTotalSeconds(skipOrder.getTotalSeconds());//每次跳档记录的总时长（秒）
        ebOrderService.updateRow(ebOrder);

        orderSkipService.delete(skipOrder.getChargeOrderSkipId());

        saveChargeData(order.getComId(),order.getChargeOrderId(),OrderAction.EB.SlipPower,new Date(),"","更新充电时间成功！");
    }

    /**
     * 微信支付回调
     *
     * @param
     */
    public void baofuWxPayNotify(String outTradeNo,String transactionId,String successTime) {
//        WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = null;
//        try {
//            wxManager.getPayService(comId);
//            wxPayOrderNotifyV3Result = wxPayService.parseOrderNotify(request);
//        } catch (WxPayException e) {
//            log.error("解析微信支付通知失败", e);
//        }

        Order order = orderService.getRow("out_trade_no",outTradeNo);
        if (null == order) {
            log.error("订单" + outTradeNo + "不存在！");
            return;
        }
        order.setTransactionId(transactionId);
        orderService.updateRow(order);

        self.orderPaid(order.getOrderNo(),
                DateUtil.parse(successTime));
    }

    private void baofuRefund(String outRefundNo) {
        //查询明细数据
        List<BaofuAccountDetails> details = baofuAccountDetailsService.getRows(new String[]{"out_trade_no","account_type"}, new Object[]{outRefundNo,FinancialEnum.IncomeOrExpend.Income.name()});
        if(details!=null && details.size()>0){
            List<BaofuAccountDetails> addDetails =new ArrayList<>();
            ValuesActionEntity actionEntity = new ValuesActionEntity();
            List<ValuesAcctInfoEntity> acctInfo =  new ArrayList<>();
            ValuesAcctInfoEntity acctInfoEntity =  null;
            String transSerialNo =OrderUtil.getTxOrderNo();
            Integer dealAmount = 0;
            for(BaofuAccountDetails vo:details){
                acctInfoEntity = new ValuesAcctInfoEntity();
                acctInfoEntity.setContractNo(vo.getContractNo());
                acctInfoEntity.setTransAmount(new BigDecimal(vo.getCommission()).divide(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_HALF_UP).toString());
                acctInfoEntity.setRemark("订单："+vo.getOutTradeNo()+"进行比退款");
                dealAmount = dealAmount + vo.getCommission();
                acctInfo.add(acctInfoEntity);
                //写人账户明细数据
                BaofuAccountDetails accountDetails = new BaofuAccountDetails();
                accountDetails.setCommissionId(vo.getCommissionId());
                accountDetails.setContractNo(vo.getContractNo());
                accountDetails.setCommission(vo.getCommission());
                accountDetails.setCommissionRate(vo.getCommissionRate());
                accountDetails.setChargeOrderId(vo.getChargeOrderId());
                accountDetails.setTransSerialNo(transSerialNo);
                accountDetails.setOutTradeNo(vo.getOutTradeNo());
                accountDetails.setOrderAmount(vo.getOrderAmount());
                accountDetails.setAccountType(FinancialEnum.IncomeOrExpend.Expend.name());
                accountDetails.setType(vo.getType());
                accountDetails.setCreateTime(new Date());
                //accountDetails.setBaofuAccountDetailsId(UUID.randomUUID().toString().replaceAll("-",""));
                addDetails.add(accountDetails);
            }
            actionEntity.setAcctInfo(acctInfo);
            actionEntity.setTransOrderNo("TSN"+ FormatUtil.CreateAeskey(20));
            actionEntity.setTransSerialNo(transSerialNo);
            actionEntity.setOrderNo(outRefundNo);
            actionEntity.setDealAmount(new BigDecimal(dealAmount).divide(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
            ContentBodyEntity<RsultBodyEntity> contentBody = baoFuAccountService.BCT3_5002_001_01(actionEntity);
            if (contentBody.getBody().getState() == 1){
                //添加宝付流水
                if(addDetails!=null && addDetails.size()>0){
                    for(BaofuAccountDetails vo:addDetails){
                        baofuAccountDetailsService.saveRow(vo);
                    }
                }
            }
        }
    }
}
